<?php
/*
* Kusht Mud.
* ----
* The MIT License
* Copyright (c) 2010 Andrew Tutt
* ----
*/

/* Character Class
*
* This is the Game Object for a ALL Characters including NPC MOBs
*/

/* 
* 	Note that:
*   hitroll, damroll, armor, max_move, max_hit, max_mana
*
*/

require_once "BaseObject.class.inc";

class Character extends BaseObject {	
	public $ignore_list = array(); // People you do not hear tells from
	public $carrying = array();	// The stuff on the person
	public $carry_weight;
	public $carry_number;

	public $hit;
	public $max_hit;
	public $mana;
	public $max_mana;
	public $stamina;
	public $max_stamina;
	
	public $hitroll;
	public $damroll;
	public $savingthrow;
	
	public $flee;				// The % of exp when you start automatically trying to run away
	public $alignment;
	public $level; 				// Level
	public $experience;			// How you gain levels (even c. 2010)
	public $level_points;		// What you earn for leveling up (you can spend them on new skills)
								// Yes, we want NPCs to be able to level and become cooler, why not?
	
	public $wait; 				// Whatever you last did, forces you to wait a certain number of clicks 
								// (only certain commands check for wait however, so you can talk still

	public $bulk;					// In this game, this is Con & Str
	public $intelligence;
	public $ingenuity;				// Anyone who's ever met a really dumb smart person understands this one
	public $speed;
	public $magnetism; 				// As in Cassanova, not Superconductor
	public $connections;			// This is that trait nobody wants but everybody needs	
	
	// Modifiers
	public $bulk_mod;
	public $intelligence_mod;
	public $ingenuity_mod;
	public $speed_mod;
	public $magnetism_mod;
	public $connections_mod;
	
	// MetaText I can Edit (like notes): 
	// We handle unpublished MetaText via MetaText Handlers, 
	// not on characters (see the world class)
	
	// If you want an even longer description, use a MetaText and a MarkupLink;
	
	// Deal with People Whom the Player is Interacting With
	public $char_master;		// They issue your commands for you, locking you out and you follow them (charm, pet, etc.)
	public $group_leader;		// The person in charge of your group -- Can be extended to grant limited coordination to Group Leader
	public $char_fighting;		// Who the characer is currently Fighting. Note that you simply cannot fight more than one character,
								// Though more than one can fight YOU!
	public $reply;				// The character who last spoke to you (might be useful for npcs too you know)
	
	/* ----------- Vars set in All_Flags ------------- */
	// Sex: Set in All_Flags
	// Class: Set in All_Flags (Knight, etc.)
	// Race: Set in All_Flags (Who knows what the races are though...)
	// Position (standing, dead, sleeping): Set in All_Flags
	// Admin_level: Set in All_Flags
	// Deaf / Mute: Definitely set in all flags
	
	function force_cmd($cmd,$phrase) {
		cmdHandler::processCmd($this,$cmd,$phrase);
	}
	
	function move($exit_) {
		cmdHandler::act ($this,"?n leaves ?T.", NULL, $exit_->tellOthers." ".$exit_->name, TO_ROOM);
		$this->move_to($exit_->to_room);
	}
	
	function move_to($room) {
		//if (!is_affected (AFF_SNEAK))
		$this->in_room()->rmv_char($this);
		$room->add_char($this);
		//if (!is_affected (AFF_SNEAK))
    	cmdHandler::act ($this,"?n has arrived.", NULL, NULL, TO_ROOM);
	}
	
	// Demonstration of special flag handling
	// We will serialize this info soon...
	function setposition($flag) {
		$this->rmv($this->position());
		$this->set($flag);
	}
	
	function in_good_position($pos) {
		if($this->position() < $pos) {
			switch ($this->position()) {
			case DEAD:
			  $this->send("Lie still; you are DEAD.");
			  break;
			case MORTAL:
			case INCAP:
			  $this->send("You are hurt far too bad for that.\r\n");
			  break;
			case STUNNED:
			  $this->send("You are too stunned to do that.");
			  break;
			case SLEEPING:
			  $this->send("In your dreams, or what?");
			  break;
			case RESTING:
			  $this->send("Nah... You feel too relaxed...");
			  break;
			case FIGHTING:
			  $this->send("No way!  You are still fighting!");
			  break;
			}
			return false;
		}
		return true;
	}
	
	function in_bad_position($p) {
		return !$this->in_good_position($p);
	}
	
	function position() {
		// This function is a good prototype for a 
		// more abstract funcion we could write if we needed/wanted to
		$i = DEAD; // Lowest position flag
		while($i <= STANDING) { // until highest position flag
			if($this->is($i)) { return $i; }
			$i++;
		}
		return DEAD; // Avoid Errors 
	}
	
	function sex() {
		$i = NOGENDER;
		while($i <= FEMALE) { // until highest position flag
			if($this->is($i)) { return $i; }
			$i++;
		}
		return NOGENDER; // Avoid Errors
	}
	
	function is_awake() {
		return $this->position() > SLEEPING;
	}
	
	function describe_to ($looker) {
		if ($looker->can_see($this)) {
			return $this->name;
		} else {
			return "someone";
		}
	}
	
	// True: Can See Person / Object
	// Order matters!
	function can_see($object) {
		// Player
		if($this->is(BLIND)) { return false; }
		if($this===$object) { return true; }
		if($this->has(HOLYLIGHT)) { return true; }
		if($object->is(HIDING) && !$this->has(DETECT_HIDDEN)) { return false; }	
		
		// Object
		if($object->is(POTION)) { return true; }
		if($object->is(LIGHT) && !$object->is(BROKEN)) { return true; } // The light has not burned out...
		
		// Both
		if($object->is(INVISIBLE) && !$this->has(DETECT_INVIS)) { return false; }
		
		// Room
		if($in_room->is(DARK) && !$this->has(INFRARED)) { return false; }	
				
		return true;
	}
		
	/*
	 * True if char can drop obj.
	 */
	function can_drop($object) {
		if(!$object->is(NOT_DROPPABLE)) { return true; }
		if(level >= IMMORTAL) { return true; }
		
		return false;
	}
		
	function is_good() {
		return $this->alignment >= 350;
	}
	
	function is_evil() {
		return $this->alignment <= -350;
	}
	
	function is_neutral() {
		return !$this->is_good && !$this->is_evil();
	}
	
	function is_outside() {
		return !$this->in_room->is(INDOORS);
	}
	
	// Find equipment on a character
	function get_eq($worn_at_target_location) {
		foreach($this->carrying as $item) {
			if($item->is($worn_at_target_location)) { return $item; }
		}
		return false;
	}
	
}

?>